package models

import (
	"errors"
	"fmt"
	"time"

	"github.com/beego/beego/v2/client/orm"
)

// MemberCheckin 会员签到记录模型
type MemberCheckin struct {
	BaseModel
	MemberId     int64  `orm:"index" json:"member_id"`       // 会员ID
	CheckinDate  string `orm:"size(10)" json:"checkin_date"` // 签到日期，格式：YYYY-MM-DD
	CheckinTime  int64  `json:"checkin_time"`                // 签到时间戳
	PointsReward int    `json:"points_reward"`               // 获得积分奖励
	Days         int    `json:"days"`                        // 当前连续签到天数
	ClientIp     string `orm:"size(50)" json:"client_ip"`    // 客户端IP
}

// MemberCheckinDays 会员签到统计模型
type MemberCheckinDays struct {
	BaseModel
	MemberId          int64  `orm:"index" json:"member_id"`            // 会员ID
	LastCheckinDate   string `orm:"size(10)" json:"last_checkin_date"` // 最后签到日期
	ConsecutiveDays   int    `json:"consecutive_days"`                 // 当前连续签到天数
	CumulativeDays    int    `json:"cumulative_days"`                  // 累计签到天数
	LastPointsReward  int    `json:"last_points_reward"`               // 最后一次签到获得的积分
	TotalPointsReward int    `json:"total_points_reward"`              // 累计获得的签到积分
}

// TableName 设置表名
func (m *MemberCheckin) TableName() string {
	return "ss_member_checkin"
}

// TableName 设置表名
func (m *MemberCheckinDays) TableName() string {
	return "ss_member_checkin_days"
}

// 获取今日签到奖励积分
func GetCheckinPointsReward(consecutiveDays int) int {
	// 根据连续签到天数返回不同的积分奖励
	switch {
	case consecutiveDays == 0: // 第1天
		return 20
	case consecutiveDays == 1: // 第2天
		return 30
	case consecutiveDays == 2: // 第3天
		return 50
	case consecutiveDays == 3: // 第4天
		return 80
	case consecutiveDays == 4: // 第5天
		return 130
	case consecutiveDays == 5: // 第6天
		return 180
	case consecutiveDays == 6: // 第7天，特殊奖励
		return 300
	default:
		return 20 // 超过7天后重新开始，给予基础积分
	}
}

// CheckMemberCheckinToday 检查会员今日是否已签到
func CheckMemberCheckinToday(memberId int64) (bool, error) {
	if memberId <= 0 {
		return false, errors.New("会员ID无效")
	}

	// 获取今日日期
	todayDate := time.Now().Format("2006-01-02")

	// 查询今日是否已签到
	o := orm.NewOrm()
	exist := o.QueryTable(new(MemberCheckin)).
		Filter("member_id", memberId).
		Filter("checkin_date", todayDate).
		Exist()

	return exist, nil
}

// GetMemberCheckinInfo 获取会员签到信息
func GetMemberCheckinInfo(memberId int64) (*MemberCheckinDays, error) {
	if memberId <= 0 {
		return nil, errors.New("会员ID无效")
	}

	o := orm.NewOrm()
	checkinInfo := &MemberCheckinDays{MemberId: memberId}
	err := o.Read(checkinInfo, "MemberId")

	// 如果没有记录，创建一个新的记录
	if err == orm.ErrNoRows {
		checkinInfo = &MemberCheckinDays{
			MemberId:          memberId,
			LastCheckinDate:   "",
			ConsecutiveDays:   0,
			CumulativeDays:    0,
			LastPointsReward:  0,
			TotalPointsReward: 0,
		}
		_, err = o.Insert(checkinInfo)
		if err != nil {
			return nil, err
		}
		return checkinInfo, nil
	}

	return checkinInfo, err
}

// DoMemberCheckin 执行会员签到
func DoMemberCheckin(memberId int64, clientIp string, franchiseId int64) (*MemberCheckin, error) {
	if memberId <= 0 {
		return nil, errors.New("会员ID无效")
	}

	// 获取当前时间
	now := time.Now()
	todayDate := now.Format("2006-01-02")
	yesterdayDate := now.AddDate(0, 0, -1).Format("2006-01-02")

	// 开始事务
	o := orm.NewOrm()
	tx, err := o.Begin()
	if err != nil {
		return nil, err
	}

	// 检查今日是否已签到
	hasCheckin, err := CheckMemberCheckinToday(memberId)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	if hasCheckin {
		tx.Rollback()
		return nil, errors.New("今日已签到")
	}

	// 获取签到统计信息
	checkinDays, err := GetMemberCheckinInfo(memberId)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	// 判断是否连续签到
	isConsecutive := checkinDays.LastCheckinDate == yesterdayDate

	// 处理连续签到天数
	if isConsecutive {
		checkinDays.ConsecutiveDays++
		if checkinDays.ConsecutiveDays > 7 {
			// 超过7天循环，重置为1
			checkinDays.ConsecutiveDays = checkinDays.ConsecutiveDays % 7
			if checkinDays.ConsecutiveDays == 0 {
				checkinDays.ConsecutiveDays = 7
			}
		}
	} else {
		checkinDays.ConsecutiveDays = 1
	}

	// 计算积分奖励
	pointsReward := GetCheckinPointsReward(checkinDays.ConsecutiveDays - 1)

	// 创建签到记录
	checkin := &MemberCheckin{
		MemberId:     memberId,
		CheckinDate:  todayDate,
		CheckinTime:  now.Unix(),
		PointsReward: pointsReward,
		Days:         checkinDays.ConsecutiveDays,
		ClientIp:     clientIp,
	}

	// 插入签到记录
	_, err = tx.Insert(checkin)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	// 更新签到统计信息
	checkinDays.LastCheckinDate = todayDate
	checkinDays.CumulativeDays++
	checkinDays.LastPointsReward = pointsReward
	checkinDays.TotalPointsReward += pointsReward

	_, err = tx.Update(checkinDays)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	// 提交事务
	err = tx.Commit()
	if err != nil {
		return nil, err
	}

	// 更新会员积分并添加积分变动记录
	// 使用独立事务，避免与上面的事务冲突
	desc := fmt.Sprintf("第%d天连续签到奖励", checkin.Days)
	err = AddMemberPoints(memberId, pointsReward, 4, "", desc, "system", franchiseId)
	if err != nil {
		return nil, err
	}

	return checkin, nil
}

// GetMemberCheckinHistory 获取会员签到历史记录
func GetMemberCheckinHistory(memberId int64, year, month int) ([]*MemberCheckin, error) {
	if memberId <= 0 {
		return nil, errors.New("会员ID无效")
	}

	o := orm.NewOrm()
	var checkins []*MemberCheckin

	// 构建查询条件
	query := o.QueryTable(new(MemberCheckin)).Filter("member_id", memberId)

	if year > 0 && month > 0 {
		startDate := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
		endDate := startDate.AddDate(0, 1, 0)

		startDateStr := startDate.Format("2006-01-02")
		endDateStr := endDate.Format("2006-01-02")

		query = query.Filter("checkin_date__gte", startDateStr).Filter("checkin_date__lt", endDateStr)
	}

	_, err := query.OrderBy("-checkin_date").All(&checkins)
	return checkins, err
}
